home *** CD-ROM | disk | FTP | other *** search
/ Amiga Format CD 49 / Amiga Format CD49 (2000-01-17)(Future Publishing)(GB)(Track 1 of 3)[!][issue 2000-02].iso / +system+ / tools / sound / ahi / developer / devloper.lzx / examples / Device / AHI-Handler / RCS / main.c,v
Text File  |  1979-08-21  |  60KB  |  2,379 lines

  1. head    4.2;
  2. access;
  3. symbols;
  4. locks; strict;
  5. comment    @ * @;
  6.  
  7.  
  8. 4.2
  9. date    97.04.09.01.55.32;    author lcs;    state Exp;
  10. branches;
  11. next    4.1;
  12.  
  13. 4.1
  14. date    97.04.02.22.46.37;    author lcs;    state Exp;
  15. branches;
  16. next    1.8;
  17.  
  18. 1.8
  19. date    97.03.27.12.11.25;    author lcs;    state Exp;
  20. branches;
  21. next    1.7;
  22.  
  23. 1.7
  24. date    97.03.26.13.32.43;    author lcs;    state Exp;
  25. branches;
  26. next    1.6;
  27.  
  28. 1.6
  29. date    97.02.01.14.10.08;    author lcs;    state Exp;
  30. branches;
  31. next    1.5;
  32.  
  33. 1.5
  34. date    97.01.29.15.44.49;    author lcs;    state Exp;
  35. branches;
  36. next    1.4;
  37.  
  38. 1.4
  39. date    97.01.24.23.20.47;    author lcs;    state Exp;
  40. branches;
  41. next    1.3;
  42.  
  43. 1.3
  44. date    97.01.23.19.55.50;    author lcs;    state Exp;
  45. branches;
  46. next    1.2;
  47.  
  48. 1.2
  49. date    97.01.21.23.56.21;    author lcs;    state Exp;
  50. branches;
  51. next    1.1;
  52.  
  53. 1.1
  54. date    97.01.17.23.34.28;    author lcs;    state Exp;
  55. branches;
  56. next    ;
  57.  
  58.  
  59. desc
  60. @Handler for /dev/audio-like device using AHI
  61. @
  62.  
  63.  
  64. 4.2
  65. log
  66. @Much improved error handling.
  67. @
  68. text
  69. @/* $Id: main.c,v 4.1 1997/04/02 22:46:37 lcs Exp lcs $
  70.  * $Log: main.c,v $
  71.  * Revision 4.1  1997/04/02  22:46:37  lcs
  72.  * Bumped to version 4
  73.  *
  74.  * Revision 1.8  1997/03/27  12:11:25  lcs
  75.  * Never mind! Bah.
  76.  *
  77.  * Revision 1.7  1997/03/26  13:32:43  lcs
  78.  * Added UNIT to the template, and set taskpri to 5.
  79.  *
  80.  * Revision 1.6  1997/02/01  14:10:08  lcs
  81.  * A couple of bugs fixed.
  82.  *
  83.  * Revision 1.5  1997/01/29  15:44:49  lcs
  84.  * It's "finished"!
  85.  *
  86.  * Revision 1.4  1997/01/24  23:20:47  lcs
  87.  * Writing seem to work too...
  88.  *
  89.  * Revision 1.3  1997/01/23  19:55:50  lcs
  90.  * Added AIFF and AIFC saving.
  91.  *
  92.  * Revision 1.2  1997/01/21  23:56:21  lcs
  93.  * Reading seem to work okay now.
  94.  *
  95.  * Revision 1.1  1997/01/17  23:34:28  lcs
  96.  * Initial revision
  97.  *
  98.  */
  99.  
  100. /*
  101.  * This code is written using DICE, and is based on the DosHan example
  102.  * source code that came with the compiler. Not all comments are mine,
  103.  * by the way... 
  104.  *
  105.  * Done by Martin Blom 1997. Public Domain.
  106.  *
  107.  */
  108.  
  109.  
  110. #include <exec/types.h>
  111. #include <exec/nodes.h>
  112. #include <exec/ports.h>
  113. #include <exec/memory.h>
  114. #include <dos/dos.h>
  115. #include <dos/dosextens.h>
  116. #include <dos/filehandler.h>
  117. #include <dos/rdargs.h>
  118.  
  119. #include <devices/ahi.h>
  120. #include <proto/ahi.h>
  121.  
  122. #include <clib/exec_protos.h>
  123. #include <clib/alib_protos.h>
  124. #include <clib/dos_protos.h>
  125. #include <clib/utility_protos.h>
  126.  
  127. #include <stdio.h>
  128. #include <stdarg.h>
  129. #include <stdlib.h>
  130. #include <string.h>
  131.  
  132. #include "main.h"
  133.  
  134.  
  135. /*
  136.  *  Prototypes
  137.  */
  138.  
  139. LONG PlayAndSwap(struct HandlerData *, LONG);
  140. long extended2long(extended *);
  141. void ulong2extended (ULONG, extended *);
  142. void FillAIFFheader(struct HandlerData *);
  143. void FillAIFCheader(struct HandlerData *);
  144. LONG ReadCOMMchunk(struct HandlerData *, UBYTE *, LONG);
  145. long AllocAudio(int);
  146. void FreeAudio(void);
  147. long ParseArgs(struct HandlerData *, char *);
  148. long InitHData(struct HandlerData *);
  149. void FreeHData(struct HandlerData *);
  150. void returnpacket (struct DosPacket *);
  151. void Initialize (void);
  152. void UnInitialize (void);
  153.  
  154.  
  155. /*
  156.  *  Some macros
  157.  */
  158.  
  159. #define min(a,b) ((a)<=(b)?(a):(b))
  160. #define DOS_TRUE    -1
  161. #define DOS_FALSE   0
  162. #define BTOC(bptr)  ((void *)((long)(bptr) << 2))
  163. #define CTOB(cptr)  ((BPTR)(((long)cptr) >> 2))
  164.  
  165.  
  166. /*
  167.  *  My debug stuff....
  168.  */
  169.  
  170. #define HIT(x) {char *a=NULL; *a=x;}
  171. void kprintf(char *, ...);
  172.  
  173.  
  174. /*
  175.  *  Global variables
  176.  */
  177.  
  178. const static char ID[] = "$VER: AHI-Handler 4.2 (9.4.97)\r\n";
  179.  
  180. struct List        HanList;
  181. struct DeviceNode *DevNode;
  182. struct MsgPort    *PktPort;
  183. int                AllocCnt;
  184. BOOL               Running;
  185.  
  186. struct MsgPort    *AHImp     = NULL;
  187. struct AHIRequest *AHIio     = NULL;
  188. BYTE               AHIDevice = -1;
  189. struct Library    *AHIBase;
  190.  
  191. struct AIFCHeader AIFCHeader = {
  192.   ID_FORM, NULL, ID_AIFC,
  193.   ID_FVER, sizeof(FormatVersionHeader), {
  194.     AIFCVersion1
  195.   },
  196.   ID_COMM, sizeof(ExtCommonChunk), {
  197.     0,
  198.     0,
  199.     0,
  200.     {0},
  201.     NO_COMPRESSION,
  202.     sizeof("not compressed")-1,
  203.     'n','o','t',' ','c','o','m','p','r','e','s','s','e','d'
  204.   },
  205.   ID_SSND, NULL, {0,0}
  206. };
  207.  
  208. struct AIFFHeader AIFFHeader = {
  209.   ID_FORM, NULL, ID_AIFF,
  210.   ID_COMM, sizeof(CommonChunk),{
  211.     0,
  212.     0,
  213.     0,
  214.     {0}
  215.   },
  216.   ID_SSND, NULL, {0,0}
  217. };
  218.  
  219.  
  220. /******************************************************************************
  221. **** Entry ********************************************************************
  222. ******************************************************************************/
  223.  
  224. /*
  225.  *  Note that we use the _main entry point.  Also notice that we do not
  226.  *  need to open any libraries.. they are openned for us via DICE's
  227.  *  unique auto-library-open ability.
  228.  */
  229.  
  230. void _main ()
  231. {
  232.   struct DosPacket *packet;
  233.   struct Process *proc = (struct Process *) FindTask (NULL);
  234.  
  235.   PktPort = &proc->pr_MsgPort;
  236.   NewList (&HanList);
  237.   Initialize ();
  238.  
  239.   Running = TRUE;
  240.   AllocCnt = 0;
  241.  
  242. #ifdef DEBUG
  243.   kprintf("Init\n");
  244. #endif
  245.  
  246.   /*
  247.    *        Main Loop
  248.    */
  249.  
  250.   while(Running) {
  251.     struct Message *msg;
  252.  
  253.     while ((msg = GetMsg (PktPort)) == NULL)
  254.       Wait (1 << PktPort->mp_SigBit);
  255.     packet = (struct DosPacket *) msg->mn_Node.ln_Name;
  256.  
  257.     /*
  258.      *  default return value
  259.      */
  260.  
  261.     packet->dp_Res1 = DOS_TRUE;
  262.     packet->dp_Res2 = 0;
  263.  
  264.     /*
  265.      *  switch on packet
  266.      */
  267.  
  268.     switch (packet->dp_Type) {
  269.  
  270.       case ACTION_DIE:        /*  ??? */
  271.       {
  272.         break;
  273.       }
  274.  
  275.       /***********************************************************************/
  276.  
  277.       case ACTION_FINDUPDATE: /*  FileHandle,Lock,Name        Bool        */
  278.       case ACTION_FINDINPUT:  /*  FileHandle,Lock,Name        Bool        */
  279.       case ACTION_FINDOUTPUT: /*  FileHandle,Lock,Name        Bool        */
  280.       {
  281.         struct FileHandle *fh = BTOC (packet->dp_Arg1);
  282.         unsigned char *base = BTOC (packet->dp_Arg3);
  283.         int len = *base;
  284.         char buf[128];
  285.         struct HandlerData *data;
  286.         int unit = AHI_DEFAULT_UNIT;
  287.  
  288.         // Skip volume name and ':'
  289.  
  290.         while(*++base != ':')
  291.           --len;
  292.         ++base;
  293.  
  294.         {
  295.           // Convert /'s to blanks
  296.  
  297.           char *p = base;
  298.  
  299.           while(*++p)
  300.             if(*p == '/')
  301.               *p = ' ';
  302.         }
  303.  
  304.         if (len >= sizeof (buf))
  305.           len = sizeof (buf) - 1;
  306.  
  307.         strncpy (buf, base, len - 1);
  308.         buf[len - 1] = '\n';
  309.         buf[len] = 0;
  310.  
  311. #ifdef DEBUG
  312.         kprintf("ACTION_FIND#?: %s\n", (char *) buf);
  313. #endif
  314.  
  315.         data = AllocVec(sizeof(struct HandlerData), MEMF_PUBLIC | MEMF_CLEAR);
  316.         if(! data) {
  317.           packet->dp_Res1 = DOS_FALSE;
  318.           packet->dp_Res2 = ERROR_NO_FREE_STORE;
  319.           break;
  320.         }
  321.  
  322.         if(packet->dp_Res2 = ParseArgs(data, (char *) buf)) {
  323.           FreeHData(data);
  324.           packet->dp_Res1 = DOS_FALSE;
  325.           break;
  326.         }
  327.  
  328.         if(data->args.unit) {
  329.           unit = *data->args.unit;
  330.         }
  331.  
  332.         if(packet->dp_Res2 = AllocAudio(unit)) {
  333.           FreeAudio();
  334.           FreeHData(data);
  335.           packet->dp_Res1 = DOS_FALSE;
  336.           break;
  337.         }
  338.  
  339.  
  340.         fh->fh_Arg1 = (ULONG) data;
  341.         fh->fh_Port = (struct MsgPort *) DOS_TRUE;
  342.         break;
  343.       }
  344.  
  345.       /***********************************************************************/
  346.  
  347.       case ACTION_READ:        /*  FHArg1,CPTRBuffer,Length    ActLength   */
  348.       {
  349.  
  350.         /*
  351.          *   Reading is straightforward except for handling EOF... We
  352.          *  must guarentee a return value of 0 (no bytes left) before
  353.          *  beginning to return EOFs (-1's).  If we return a negative
  354.          *  number right off programs like COPY will assume a failure
  355.          *  (if AUDIO: is the source) and delete the destination file.
  356.          *
  357.          *  The basic idea is to feed the packets from one buffer while
  358.          *  recording asyncroniously to the other. When we have read
  359.          *  the buffer, we wait until the other is filled, and switch
  360.          *  buffer pointers.
  361.          */
  362.  
  363.         struct HandlerData *data = (struct HandlerData *) packet->dp_Arg1;
  364.         UBYTE *dest   = (void *) packet->dp_Arg2;
  365.         LONG   length, filled;
  366.  
  367. #ifdef DEBUG
  368.         kprintf("ACTION_READ: 0x%08lx, %ld\n", packet->dp_Arg2, packet->dp_Arg3);
  369. #endif
  370.  
  371.         if(! data->initialized) {
  372.           packet->dp_Res2 = InitHData(data);
  373.           if(packet->dp_Res2) {
  374.             packet->dp_Res1 = -1;
  375.             break;
  376.           }
  377.         }
  378.  
  379.         length = filled = min(data->totallength, packet->dp_Arg3);
  380.  
  381.         if(length <= 0) {
  382.           packet->dp_Res1 = length;
  383.           data->totallength = -1;
  384.           break;
  385.         }
  386.  
  387.         if(data->buffer1 == NULL) {
  388.  
  389.           data->buffer1 = AllocVec(data->buffersize, MEMF_PUBLIC);
  390.           data->buffer2 = AllocVec(data->buffersize, MEMF_PUBLIC);
  391.           data->readreq    = AllocVec(sizeof (struct AHIRequest), MEMF_PUBLIC);
  392.  
  393.           if((data->buffer1 == NULL)
  394.           || (data->buffer2 == NULL)
  395.           || (data->readreq    == NULL)) {
  396.             packet->dp_Res1 = -1;
  397.             packet->dp_Res2 = ERROR_NO_FREE_STORE;
  398.             break;
  399.           }
  400.  
  401.           CopyMem(AHIio, data->readreq, sizeof (struct AHIRequest));
  402.  
  403.           // Fill buffer 2
  404.           // Note that io_Offset is always 0 the first time
  405.  
  406.           data->readreq->ahir_Std.io_Command  = CMD_READ;
  407.           data->readreq->ahir_Std.io_Data     = data->buffer2;
  408.           data->readreq->ahir_Std.io_Length   = data->buffersize;
  409.           data->readreq->ahir_Std.io_Offset   = 0;
  410.           data->readreq->ahir_Type            = data->type;
  411.           data->readreq->ahir_Frequency       = data->freq;
  412.           data->readreq->ahir_Volume          = data->vol;
  413.           data->readreq->ahir_Position        = data->pos;
  414.           SendIO((struct IORequest *) data->readreq);
  415.   
  416.           // Force buffer switch filling of the other buffer
  417.  
  418.           data->length = data->offset = 0;
  419.  
  420.           // Check if we should write a header first
  421.  
  422.           if(data->format == AIFF) {
  423.             if(length < sizeof(struct AIFFHeader)) {
  424.               packet->dp_Res1 = -1;
  425.               packet->dp_Res2 = ERROR_BAD_NUMBER;
  426.               break;
  427.             }
  428.  
  429.             FillAIFFheader(data);
  430.  
  431.             CopyMem(&AIFFHeader, dest, sizeof(struct AIFFHeader)); 
  432.             dest              += sizeof(struct AIFFHeader);
  433.             length            -= sizeof(struct AIFFHeader);
  434.           }
  435.  
  436.           else if(data->format == AIFC) {
  437.             if(length < sizeof(struct AIFCHeader)) {
  438.               packet->dp_Res1 = -1;
  439.               packet->dp_Res2 = ERROR_BAD_NUMBER;
  440.               break;
  441.             }
  442.  
  443.             FillAIFCheader(data);
  444.  
  445.             CopyMem(&AIFCHeader, dest, sizeof(struct AIFCHeader)); 
  446.             dest              += sizeof(struct AIFCHeader);
  447.             length            -= sizeof(struct AIFCHeader);
  448.           }
  449.         }
  450.  
  451.  
  452.         while(length > 0) {
  453.           LONG thislength;
  454.         
  455.           if(data->offset >= data->length) {
  456.             void *temp;
  457.  
  458.             temp          = data->buffer1;
  459.             data->buffer1 = data->buffer2;
  460.             data->buffer2 = temp;
  461.  
  462.             if(WaitIO((struct IORequest *) data->readreq)) {
  463.               packet->dp_Res1 = -1;
  464.               if(data->readreq->ahir_Std.io_Error == AHIE_HALFDUPLEX) {
  465.                 packet->dp_Res2 = ERROR_OBJECT_IN_USE;
  466.               }
  467.               else {
  468.                 packet->dp_Res2 = ERROR_READ_PROTECTED;
  469.               }
  470.               break;
  471.             }
  472.  
  473.             data->length = data->readreq->ahir_Std.io_Actual;
  474.             data->offset = 0;
  475.  
  476.             data->readreq->ahir_Std.io_Command = CMD_READ;
  477.             data->readreq->ahir_Std.io_Data    = data->buffer2;
  478.             data->readreq->ahir_Std.io_Length  = data->buffersize;
  479.             data->readreq->ahir_Type           = data->type;
  480.             data->readreq->ahir_Frequency      = data->freq;
  481.             data->readreq->ahir_Volume         = data->vol;
  482.             data->readreq->ahir_Position       = data->pos;
  483.             SendIO((struct IORequest *) data->readreq);
  484.           } /* if */
  485.  
  486.           thislength = min(data->length - data->offset, length);
  487.           CopyMem(data->buffer1 + data->offset, dest, thislength); 
  488.           dest              += thislength;
  489.           length            -= thislength;
  490.           data->offset      += thislength;
  491.           data->totallength -= thislength;
  492.         } /* while */
  493.  
  494.         if(packet->dp_Res2 == 0) {
  495.           packet->dp_Res1 = filled;
  496.         }
  497.         break;
  498.  
  499.       } /* ACTION_READ */
  500.  
  501.       /***********************************************************************/
  502.  
  503.       case ACTION_WRITE:        /*  FHArg1,CPTRBuffer,Length    ActLength   */
  504.       {
  505.         struct HandlerData *data  = (struct HandlerData *) packet->dp_Arg1;
  506.         UBYTE *src    = (void *) packet->dp_Arg2;
  507.         LONG   length = packet->dp_Arg3, filled;
  508.  
  509. #ifdef DEBUG
  510.         kprintf("ACTION_WRITE: 0x%08lx, %ld\n", packet->dp_Arg2, packet->dp_Arg3);
  511. #endif
  512.  
  513.         if(data->buffer1 == NULL) {
  514.           // Check headers?
  515.  
  516.           switch(data->args.format) {
  517.             case AIFF:
  518.               if((((ULONG *) src)[0] != ID_FORM)
  519.               || (((ULONG *) src)[2] != ID_AIFF)) {
  520.                 packet->dp_Res2 = ERROR_OBJECT_WRONG_TYPE;
  521.               }
  522.               break;
  523.  
  524.             case AIFC:
  525.               if((((ULONG *) src)[0] != ID_FORM)
  526.               || (((ULONG *) src)[2] != ID_AIFC)) {
  527.                 packet->dp_Res2 = ERROR_OBJECT_WRONG_TYPE;
  528.               }
  529.               break;
  530.  
  531.             case 0:
  532.               if(((ULONG *) src)[0] == ID_FORM) {
  533.                 if(((ULONG *) src)[2] == ID_AIFF) {
  534.                   data->args.format = AIFF;
  535.                 }
  536.                 else if(((ULONG *) src)[2] == ID_AIFC) {
  537.                   data->args.format = AIFC;
  538.                 }
  539.               }
  540.               break;
  541.             
  542.             default:
  543.               break;
  544.           }
  545.  
  546.           if(packet->dp_Res2) {
  547.             packet->dp_Res1 = -1;
  548.             break;
  549.           }
  550.  
  551.           if((data->args.format == AIFF) || (data->args.format == AIFC)) {
  552.             LONG skiplen = 0;
  553.  
  554.             skiplen = ReadCOMMchunk(data, src, length);
  555.             src    += skiplen;
  556.             length -= skiplen;
  557.           }
  558.  
  559.           if(packet->dp_Res2 = InitHData(data)) {
  560.             packet->dp_Res1 = -1;
  561.             break;
  562.           }
  563.  
  564.           data->writing = TRUE;
  565.  
  566.           data->buffer1 = AllocVec(data->buffersize, MEMF_PUBLIC);
  567.           data->buffer2 = AllocVec(data->buffersize, MEMF_PUBLIC);
  568.  
  569.           if((data->buffer1 == NULL) || (data->buffer2 == NULL)) {
  570.             packet->dp_Res1 = -1;
  571.             packet->dp_Res2 = ERROR_NO_FREE_STORE;
  572.             break;
  573.           }
  574.  
  575.           data->offset = 0;
  576.           data->length = (data->buffersize / AHI_SampleFrameSize(data->type))
  577.                           * AHI_SampleFrameSize(data->type);
  578.  
  579.         }
  580.  
  581.         length = min(data->totallength, length);
  582.         filled = min(data->totallength, packet->dp_Arg3);
  583.  
  584.         while(length > 0) {
  585.           LONG thislength;
  586.         
  587.           if(data->offset >= data->length) {
  588.             packet->dp_Res2 = PlayAndSwap(data, data->length);
  589.             if(packet->dp_Res2) {
  590.               packet->dp_Res1 = -1;
  591.               break;
  592.             }
  593.           }
  594.  
  595.           thislength = min(data->length - data->offset, length);
  596.           CopyMem(src, data->buffer1 + data->offset, thislength); 
  597.           src               += thislength;
  598.           length            -= thislength;
  599.           data->offset      += thislength;
  600.           data->totallength -= thislength;
  601.  
  602.         } /* while */
  603.  
  604.         if(packet->dp_Res2 == 0) {
  605.           packet->dp_Res1 = filled;
  606.         }
  607.         break;
  608.       }
  609.  
  610.       /***********************************************************************/
  611.  
  612.       case ACTION_END:        /*  FHArg1                      Bool:TRUE   */
  613.       {
  614.         struct HandlerData *data = (struct HandlerData *) packet->dp_Arg1;
  615.  
  616. #ifdef DEBUG
  617.         kprintf("ACTION_END\n");
  618. #endif
  619.  
  620.         // Abort any reading requests
  621.  
  622.         if(data->readreq) {
  623.           AbortIO((struct IORequest *) data->readreq);
  624.           WaitIO((struct IORequest *) data->readreq);
  625.         }
  626.  
  627.         // Finish any playing requests
  628.  
  629.         if(data->writing) {
  630.           PlayAndSwap(data, data->offset);
  631.  
  632.           if(data->writereq1) {
  633.             WaitIO((struct IORequest *) data->writereq1);
  634.           }
  635.           if(data->writereq2) {
  636.             WaitIO((struct IORequest *) data->writereq2);
  637.           }
  638.         }
  639.  
  640.         FreeHData(data);
  641.         FreeAudio();
  642.  
  643.  
  644.         break;
  645.       }
  646.  
  647.       /***********************************************************************/
  648.  
  649.       case ACTION_IS_FILESYSTEM:
  650.         packet->dp_Res1 = DOS_FALSE;
  651.         break;
  652.  
  653.       /***********************************************************************/
  654.  
  655.       default:
  656.         packet->dp_Res1 = DOS_FALSE;
  657.         packet->dp_Res2 = ERROR_ACTION_NOT_KNOWN;
  658.         break;
  659.  
  660.     } /* switch */
  661.  
  662.     if(AllocCnt == 0)
  663.       Running = FALSE;
  664.  
  665.     if (packet) {
  666.       returnpacket (packet);
  667. #ifdef DEBUG
  668.       kprintf("Retured packet\n");
  669. #endif
  670.     }
  671.  
  672.   } /* for */
  673.  
  674. #ifdef DEBUG
  675.   kprintf("Dying..!\n");
  676. #endif
  677.   UnInitialize();
  678.   _exit (0);
  679. }
  680.  
  681.  
  682. /******************************************************************************
  683. **** PlayAndSwap **************************************************************
  684. ******************************************************************************/
  685.  
  686. /*
  687.  *  Starts to play the current buffer. Handles double buffering.
  688.  */
  689.  
  690. LONG PlayAndSwap(struct HandlerData *data, LONG length) {
  691.   void *temp;
  692.  
  693.   temp          = data->buffer1;
  694.   data->buffer1 = data->buffer2;
  695.   data->buffer2 = temp;
  696.  
  697.   temp            = data->writereq1;
  698.   data->writereq1 = data->writereq2;
  699.   data->writereq2 = temp;
  700.  
  701.  
  702.   if(data->writereq1 == NULL) {
  703.     data->writereq1 = AllocVec(sizeof (struct AHIRequest), MEMF_PUBLIC);
  704.  
  705.     if(data->writereq1 == NULL) {
  706.       return ERROR_NO_FREE_STORE;
  707.     }
  708.  
  709.     CopyMem(AHIio, data->writereq1, sizeof (struct AHIRequest));
  710.   }
  711.  
  712.   data->offset = 0;
  713.  
  714.   data->writereq1->ahir_Std.io_Message.mn_Node.ln_Pri = data->priority;
  715.   data->writereq1->ahir_Std.io_Command = CMD_WRITE;
  716.   data->writereq1->ahir_Std.io_Data    = data->buffer2;
  717.   data->writereq1->ahir_Std.io_Length  = length;
  718.   data->writereq1->ahir_Std.io_Offset  = 0;
  719.   data->writereq1->ahir_Type           = data->type;
  720.   data->writereq1->ahir_Frequency      = data->freq;
  721.   data->writereq1->ahir_Volume         = data->vol;
  722.   data->writereq1->ahir_Position       = data->pos;
  723.   data->writereq1->ahir_Link           = data->writereq2;
  724.   SendIO((struct IORequest *) data->writereq1);
  725.  
  726.   if(data->writereq2) {
  727.     if(WaitIO((struct IORequest *) data->writereq2)) {
  728.       if(data->writereq2->ahir_Std.io_Error == AHIE_HALFDUPLEX) {
  729.         return ERROR_OBJECT_IN_USE;
  730.       }
  731.       else {
  732.         return ERROR_WRITE_PROTECTED;
  733.       }
  734.     }
  735.   }
  736.  
  737.   return 0;
  738. }
  739.  
  740.  
  741. /******************************************************************************
  742. **** extended2long ************************************************************
  743. ******************************************************************************/
  744.  
  745. /*
  746.  *  This function translates Apples SANE Extended  used in AIFF/AIFC files
  747.  *  to a LONG. Stolen from Olaf `Olsen' Barthel's AIFF datatype.
  748.  */
  749.  
  750.  
  751. long extended2long(extended *ex)
  752. {
  753.   unsigned long mantissa;
  754.   long exponent,sign;
  755.  
  756.     // We only need 32 bits precision
  757.  
  758.   mantissa = ex->mantissa[0];
  759.  
  760.     // Is the mantissa positive or negative?
  761.  
  762.   exponent = ex->exponent;
  763.  
  764.   if(exponent & 0x8000)
  765.     sign = -1;
  766.   else
  767.     sign =  1;
  768.  
  769.     // Unbias the exponent
  770.  
  771.   exponent = (exponent & 0x7FFF) - 0x3FFF;
  772.  
  773.     // If the exponent is negative, set the mantissa to zero
  774.  
  775.   if(exponent < 0)
  776.     mantissa = 0;
  777.   else
  778.   {
  779.       // Special meaning?
  780.  
  781.     exponent -= 31;
  782.  
  783.       // Overflow?
  784.  
  785.     if(exponent > 0)
  786.       mantissa = 0x7FFFFFFF;
  787.     else
  788.       mantissa >>= -exponent; // Let the point float...
  789.   }
  790.  
  791.     // That's all...
  792.  
  793.   return(sign * (long)mantissa);
  794. }
  795.  
  796.  
  797. /******************************************************************************
  798. **** ulong2extended ***********************************************************
  799. ******************************************************************************/
  800.  
  801. /*
  802.  *  This function translates an ULONG to Apples SANE Extended
  803.  *  used in AIFF/AIFC files.
  804.  */
  805.  
  806. void ulong2extended (ULONG in, extended *ex)
  807. {
  808.   ex->exponent=31+16383;
  809.   ex->mantissa[1]=0;
  810.   while(!(in & 0x80000000))
  811.   {
  812.     ex->exponent--;
  813.     in<<=1;
  814.   }
  815.   ex->mantissa[0]=in;
  816. }
  817.  
  818.  
  819. /******************************************************************************
  820. **** FillAIFFheader ***********************************************************
  821. ******************************************************************************/
  822.  
  823. void FillAIFFheader(struct HandlerData *data) {
  824.  
  825.   AIFFHeader.FORMsize = sizeof(AIFFHeader) + data->totallength - 8;
  826.   AIFFHeader.COMMchunk.numChannels = data->channels;
  827.   AIFFHeader.COMMchunk.numSampleFrames = 
  828.       data->totallength / AHI_SampleFrameSize(data->type);
  829.   AIFFHeader.COMMchunk.sampleSize = data->bits;
  830.   ulong2extended(data->freq, &AIFFHeader.COMMchunk.sampleRate);
  831.   AIFFHeader.SSNDsize = sizeof(SampledSoundHeader) + data->totallength;
  832. }
  833.  
  834.  
  835. /******************************************************************************
  836. **** FillAIFCheader ***********************************************************
  837. ******************************************************************************/
  838.  
  839. void FillAIFCheader(struct HandlerData *data) {
  840.  
  841.   AIFCHeader.FORMsize = sizeof(AIFCHeader) + data->totallength - 8;
  842.   AIFCHeader.COMMchunk.numChannels = data->channels;
  843.   AIFCHeader.COMMchunk.numSampleFrames = 
  844.       data->totallength / AHI_SampleFrameSize(data->type);
  845.   AIFCHeader.COMMchunk.sampleSize = data->bits;
  846.   ulong2extended(data->freq, &AIFCHeader.COMMchunk.sampleRate);
  847.   AIFCHeader.SSNDsize = sizeof(SampledSoundHeader) + data->totallength;
  848. }
  849.  
  850.  
  851. /******************************************************************************
  852. **** ReadCOMMchunk ************************************************************
  853. ******************************************************************************/
  854.  
  855. LONG ReadCOMMchunk(struct HandlerData *data, UBYTE *buffer, LONG length) {
  856.   UWORD *src = (UWORD *) buffer;
  857.   LONG   len = (length >> 1) - 2;
  858.   ExtCommonChunk *common;
  859.  
  860.   while(len > 0) {
  861.     if(((ULONG *) src)[0] == ID_COMM) {
  862.       common = (ExtCommonChunk *) (src + 4);
  863.       data->channels    = common->numChannels;
  864.       data->bits        = common->sampleSize;
  865.       data->totallength = common->numSampleFrames * common->numChannels *
  866.           (data->bits <= 8 ? 1 : (data->bits <= 16 ? 2 : (data->bits <= 32 ? 4 : 0)));
  867.       data->freq = extended2long(&common->sampleRate);
  868.  
  869.       if(!data->args.channels)
  870.         data->args.channels = &data->channels;
  871.       if(!data->args.bits)
  872.         data->args.bits     = &data->bits;
  873.       if(!data->args.length)
  874.         data->args.length   = &data->totallength;
  875.       if(!data->args.freq)
  876.         data->args.freq     = &data->freq;
  877.     }
  878.     else if(((ULONG *) src)[0] == ID_SSND) {
  879.       src += 8;
  880.       break;
  881.     }
  882.     src++;
  883.     len--;
  884.   }
  885.   return (LONG) src - (LONG) buffer;
  886. }
  887.  
  888. /******************************************************************************
  889. **** AllocAudio ***************************************************************
  890. ******************************************************************************/
  891.  
  892. /*
  893.  *  If the device isn't already open, open it now
  894.  */
  895.  
  896. long AllocAudio(int unit) {
  897.   long rc = 0;
  898.  
  899.   if(++AllocCnt == 1) {
  900.     if(AHImp=CreateMsgPort()) {
  901.       if(AHIio=(struct AHIRequest *)CreateIORequest(AHImp,sizeof(struct AHIRequest))) {
  902.         AHIio->ahir_Version = 4;
  903.         AHIDevice=OpenDevice(AHINAME,unit,(struct IORequest *)AHIio,NULL);
  904.       }
  905.     }
  906.  
  907.     if(AHIDevice) {
  908.       rc = ERROR_OBJECT_NOT_FOUND;
  909.     }
  910.     else {
  911.       AHIBase=(struct Library *)AHIio->ahir_Std.io_Device;
  912.     }
  913.   }
  914.   return rc;
  915. }
  916.  
  917.  
  918. /******************************************************************************
  919. **** FreeAudio ****************************************************************
  920. ******************************************************************************/
  921.  
  922. /*
  923.  *  If we're the last user, close the device now
  924.  */
  925.  
  926. void FreeAudio(void)
  927. {
  928.   if(--AllocCnt == 0) {
  929.     if(AHIDevice == 0)
  930.       CloseDevice((struct IORequest *)AHIio);
  931.     AHIDevice = -1;
  932.     DeleteIORequest((struct IORequest *)AHIio);
  933.     AHIio = NULL;
  934.     DeleteMsgPort(AHImp);
  935.     AHImp = NULL;
  936.   }
  937. }
  938.  
  939.  
  940. /******************************************************************************
  941. **** ParseArgs ****************************************************************
  942. ******************************************************************************/
  943.  
  944. /*
  945.  *  Fill out argument array. Returns 0 on success, else a DOS error code.
  946.  */
  947.  
  948. long ParseArgs(struct HandlerData *data, char *initstring) {
  949.   long rc = 0;
  950.  
  951.   data->rdargs = (struct RDArgs *) AllocDosObjectTags(DOS_RDARGS, TAG_DONE);
  952.   if(data->rdargs)
  953.   {
  954.     data->rdargs->RDA_Source.CS_Buffer = initstring;
  955.     data->rdargs->RDA_Source.CS_Length = strlen(initstring);
  956.     data->rdargs->RDA_Source.CS_CurChr = 0;
  957.     data->rdargs->RDA_Flags |= RDAF_NOPROMPT;
  958.  
  959.     data->rdargs2 = ReadArgs(
  960.       "B=BITS/K/N,C=CHANNELS/K/N,F=FREQUENCY/K/N,T=TYPE/K,V=VOLUME/K/N,P=POSITION/K/N,"
  961.       "PRI=PRIORITY/K/N,L=LENGTH/K/N,S=SECONDS/K/N,BUF=BUFFER/K/N,UNIT/K/N",
  962.       (LONG *) &data->args, data->rdargs);
  963.  
  964.     if(data->rdargs2 != NULL) {
  965.  
  966.  
  967.       if(! data->args.type) {
  968.         data->args.format = 0;
  969.       }
  970.       else if(Stricmp("SIGNED", data->args.type) == 0) {
  971.         data->args.format = SIGNED;
  972.       }
  973.       else if(Stricmp("AIFF", data->args.type) == 0) {
  974.         data->args.format = AIFF;
  975.       }
  976.       else if(Stricmp("AIFC", data->args.type) == 0) {
  977.         data->args.format = AIFC;
  978.       }
  979.       else {
  980.         rc = ERROR_BAD_TEMPLATE;
  981.       }
  982.     }
  983.     else
  984.       rc = ERROR_BAD_TEMPLATE;
  985.  
  986.   }
  987.   else
  988.     rc = ERROR_NO_FREE_STORE;
  989.  
  990.   return rc;
  991. }
  992.  
  993.  
  994. /******************************************************************************
  995. **** InitHData ****************************************************************
  996. ******************************************************************************/
  997.  
  998. /*
  999.  *  Initialize the HandlerData data structure, based on the args structure
  1000.  *  (see ParseArgs()). Returns 0 on success, else a DOS error code.
  1001.  */
  1002.  
  1003. #define S8bitmode      0
  1004. #define S16bitmode     1
  1005. #define S32bitmode     8
  1006.  
  1007. #define Sstereoflag    2
  1008.  
  1009. long InitHData(struct HandlerData *data) {
  1010.   ULONG bits = 8, channels = 1, freq = 8000;
  1011.   LONG  volume = 100, position = 0, priority = 0, 
  1012.         length = MAXINT, buffersize = 32768;
  1013.   long rc = 0;
  1014.  
  1015.   data->initialized = TRUE;
  1016.  
  1017.   // Fill in default values
  1018.  
  1019.   if(!data->args.bits)
  1020.     data->args.bits = &bits;
  1021.   if(!data->args.channels)
  1022.     data->args.channels = &channels;
  1023.   if(!data->args.freq)
  1024.     data->args.freq = &freq;
  1025.   if(!data->args.volume)
  1026.     data->args.volume = &volume;
  1027.   if(!data->args.position)
  1028.     data->args.position = &position;
  1029.   if(!data->args.priority)
  1030.     data->args.priority = &priority;
  1031.   if(!data->args.length)
  1032.     data->args.length = &length;
  1033.   if(!data->args.buffersize)
  1034.     data->args.buffersize = &buffersize;
  1035.  
  1036.   if(!data->args.format)
  1037.     data->args.format = SIGNED;
  1038.  
  1039.   // 8, 16 or 32 bit
  1040.  
  1041.   if(*data->args.bits <= 8)
  1042.     data->type = S8bitmode;
  1043.   else if(*data->args.bits <= 16)
  1044.     data->type = S16bitmode;
  1045.   else if(*data->args.bits <= 32)
  1046.     data->type = S32bitmode;
  1047.   else {
  1048.     rc = ERROR_OBJECT_WRONG_TYPE;
  1049.     goto quit;
  1050.   }
  1051.  
  1052.   // Mono or stereo
  1053.  
  1054.   if((*data->args.channels > 2) || (*data->args.channels < 1)) {
  1055.     rc = ERROR_OBJECT_WRONG_TYPE;
  1056.     goto quit;
  1057.   }
  1058.  
  1059.   if(*data->args.channels == 2)
  1060.     data->type |= Sstereoflag;
  1061.  
  1062.   data->bits     = *data->args.bits;
  1063.   data->channels = *data->args.channels;
  1064.   data->freq     = *data->args.freq;
  1065.   data->vol      = *data->args.volume * 0x10000 / 100;
  1066.   { // Don't ask why... :(
  1067.     LONG a;
  1068.     a = *data->args.position * 0x8000;
  1069.     a = a / 100 + 0x8000;
  1070.     data->pos      = a;
  1071.   }
  1072.   data->priority = *data->args.priority;
  1073.  
  1074.   if(data->args.seconds) {
  1075.     data->totallength = *data->args.seconds * data->freq 
  1076.                         * AHI_SampleFrameSize(data->type);
  1077.   }
  1078.   else {
  1079.     data->totallength = (*data->args.length / AHI_SampleFrameSize(data->type))
  1080.                         * AHI_SampleFrameSize(data->type);
  1081.   }
  1082.  
  1083.   data->format = data->args.format;
  1084.  
  1085.   switch(data->format) {
  1086.     case AIFF:
  1087.     case AIFC:
  1088.       data->totallength = data->totallength & ~1;    // Make even
  1089.       break;
  1090.   }
  1091.  
  1092.   data->buffersize = *data->args.buffersize;
  1093.  
  1094. quit:
  1095.   return rc;
  1096. }
  1097.  
  1098.  
  1099.  
  1100.  
  1101.  
  1102.  
  1103.  
  1104.  
  1105.  
  1106.  
  1107.  
  1108. /******************************************************************************
  1109. **** FreeHData ****************************************************************
  1110. ******************************************************************************/
  1111.  
  1112. /*
  1113.  *   Deallocate the HandlerData structure
  1114.  */
  1115.  
  1116. void FreeHData(struct HandlerData *data) {
  1117.   if(data) {
  1118.     if(data->rdargs2)
  1119.       FreeArgs(data->rdargs2);
  1120.     if(data->rdargs);
  1121.     FreeDosObject(DOS_RDARGS, data->rdargs);
  1122.  
  1123.     FreeVec(data->buffer1);
  1124.     FreeVec(data->buffer2);
  1125.     FreeVec(data->readreq);
  1126.     FreeVec(data->writereq1);
  1127.     FreeVec(data->writereq2);
  1128.     FreeVec(data);
  1129.   }
  1130. }
  1131.  
  1132.  
  1133. /******************************************************************************
  1134. **** returnpacket *************************************************************
  1135. ******************************************************************************/
  1136.  
  1137. /*
  1138.  *  PACKET ROUTINES.  Dos Packets are in a rather strange format as you
  1139.  *  can see by this and how the PACKET structure is extracted in the
  1140.  *  GetMsg() of the main routine.
  1141.  */
  1142.  
  1143. void returnpacket (struct DosPacket *packet) {
  1144.   struct Message *mess;
  1145.   struct MsgPort *replyPort;
  1146.  
  1147.   replyPort = packet->dp_Port;
  1148.   mess = packet->dp_Link;
  1149.   packet->dp_Port = PktPort;
  1150.   mess->mn_Node.ln_Name = (char *) packet;
  1151.   PutMsg (replyPort, mess);
  1152. }
  1153.  
  1154.  
  1155. /******************************************************************************
  1156. **** Initialize ***************************************************************
  1157. ******************************************************************************/
  1158.  
  1159. /*
  1160.  *  During initialization DOS sends us a packet and sets our dn_SegList
  1161.  *  pointer.  If we set our dn_Task pointer than every Open's go to the
  1162.  *  same handler (this one).  If we set dn_Task to NULL, every Open()
  1163.  *  will create a NEW instance of this process via the seglist, meaning
  1164.  *  our process must be reentrant (i.e. -r option).
  1165.  *
  1166.  *  note: dn_Task points to the MESSAGE PORT portion of the process
  1167.  *  (or your own custom message port).
  1168.  *
  1169.  *  If we clear the SegList then we also force DOS to reload our process
  1170.  *  from disk, but we also need some way of then UnLoadSeg()ing it ourselves,
  1171.  *  which we CANNOT do from this process since it rips our code out from
  1172.  *  under us.
  1173.  */
  1174.  
  1175. void Initialize () {
  1176.   struct DeviceNode *dn;
  1177.   struct Process *proc = (struct Process *) FindTask (NULL);
  1178.   struct DosPacket *packet;
  1179.  
  1180.   /*
  1181.    *        Handle initial message.
  1182.    */
  1183.   
  1184.   struct Message *msg;
  1185.  
  1186.   WaitPort (PktPort);
  1187.   msg = GetMsg (PktPort);
  1188.   packet = (struct DosPacket *) msg->mn_Node.ln_Name;
  1189.  
  1190.   DevNode = dn = BTOC (packet->dp_Arg3);
  1191.   dn->dn_Task = NULL;
  1192.  
  1193.   packet->dp_Res1 = DOS_TRUE;
  1194.   packet->dp_Res2 = 0;
  1195.   returnpacket (packet);
  1196. }
  1197.  
  1198.  
  1199. /******************************************************************************
  1200. **** UnInitialize *************************************************************
  1201. ******************************************************************************/
  1202.  
  1203. void UnInitialize (void) {
  1204.   struct DeviceNode *dn = DevNode;
  1205.  
  1206.   dn->dn_Task = NULL;
  1207. }
  1208. @
  1209.  
  1210.  
  1211. 4.1
  1212. log
  1213. @Bumped to version 4
  1214. @
  1215. text
  1216. @d1 1
  1217. a1 1
  1218. /* $Id: main.c,v 1.8 1997/03/27 12:11:25 lcs Exp lcs $
  1219. d3 3
  1220. d71 1
  1221. a71 1
  1222. BOOL PlayAndSwap(struct HandlerData *, LONG);
  1223. d110 1
  1224. a110 1
  1225. const static char ID[] = "$VER: AHI-Handler 4.1 (2.4.97)\r\n";
  1226. d249 1
  1227. d256 1
  1228. d267 1
  1229. d306 1
  1230. d328 1
  1231. d357 1
  1232. d371 1
  1233. d394 11
  1234. a404 1
  1235.             WaitIO((struct IORequest *) data->readreq);
  1236. a407 6
  1237.             if(data->readreq->ahir_Std.io_Error) {
  1238.               packet->dp_Res2 = ERROR_READ_PROTECTED;
  1239.               length = 0;
  1240.               break;
  1241.             }
  1242.  
  1243. d426 3
  1244. a428 1
  1245.         packet->dp_Res1 = filled;
  1246. d478 2
  1247. a479 1
  1248.           if(packet->dp_Res2)
  1249. d481 1
  1250. d491 2
  1251. a492 1
  1252.           if(packet->dp_Res2 = InitHData(data))
  1253. d494 1
  1254. d502 1
  1255. d520 2
  1256. a521 1
  1257.             if(! PlayAndSwap(data, data->length)) {
  1258. a522 1
  1259.               length = 0;
  1260. d536 3
  1261. a538 1
  1262.         packet->dp_Res1 = filled;
  1263. d588 1
  1264. a597 2
  1265.       if (packet->dp_Res2)
  1266.         packet->dp_Res1 = DOS_FALSE;
  1267. d622 1
  1268. a622 1
  1269. BOOL PlayAndSwap(struct HandlerData *data, LONG length) {
  1270. d637 3
  1271. a639 2
  1272.     if(data->writereq1 == NULL)
  1273.       return FALSE;
  1274. d659 7
  1275. a665 4
  1276.     WaitIO((struct IORequest *) data->writereq2);
  1277.  
  1278.     if(data->writereq2->ahir_Std.io_Error) {
  1279.       return FALSE;
  1280. d669 1
  1281. a669 1
  1282.   return TRUE;
  1283. @
  1284.  
  1285.  
  1286. 1.8
  1287. log
  1288. @Never mind! Bah.
  1289. @
  1290. text
  1291. @d1 1
  1292. a1 1
  1293. /* $Id: main.c,v 1.7 1997/03/26 13:32:43 lcs Exp lcs $
  1294. d3 3
  1295. d107 1
  1296. a107 1
  1297. const static char ID[] = "$VER: AHI-Handler 1.8 (27.3.97)\r\n";
  1298. d808 1
  1299. a808 1
  1300.         AHIio->ahir_Version=3;
  1301. @
  1302.  
  1303.  
  1304. 1.7
  1305. log
  1306. @Added UNIT to the template, and set taskpri to 5.
  1307. @
  1308. text
  1309. @d1 1
  1310. a1 1
  1311. /* $Id: main.c,v 1.6 1997/02/01 14:10:08 lcs Exp lcs $
  1312. d3 3
  1313. d104 1
  1314. a104 1
  1315. const static char ID[] = "$VER: AHI-Handler 1.7 (12.3.97)\r\n";
  1316. a159 4
  1317.  
  1318.   /* Boost our priority */
  1319.   
  1320.   SetTaskPri(FindTask(NULL), 5);
  1321. @
  1322.  
  1323.  
  1324. 1.6
  1325. log
  1326. @A couple of bugs fixed.
  1327. @
  1328. text
  1329. @d1 1
  1330. a1 1
  1331. /* $Id: main.c,v 1.5 1997/01/29 15:44:49 lcs Exp lcs $
  1332. d3 3
  1333. a29 47
  1334.  * Usage:  Open AUDIO: for reading, or writing. Options can be given like
  1335.  *        this: "AUDIO:PRIORITY=1 VOLUME=50". All slashes (/) in the
  1336.  *        'file' name will be translated to spaces. The removes the need
  1337.  *        for quotes: AUDIO:PRIORITY/1/VOLUME/50.
  1338.  *
  1339.  *
  1340.  *         The full template for reading is:
  1341.  *        B=BITS/K/N,C=CHANNELS/K/N,F=FREQUENCY/K/N,T=TYPE/K,
  1342.  *        L=LENGTH/K/N,S=SECONDS/K/N,BUF=BUFFER/K/N
  1343.  *
  1344.  *         The full template for writing is:
  1345.  *        B=BITS/K/N,C=CHANNELS/K/N,F=FREQUENCY/K/N,T=TYPE/K,
  1346.  *        V=VOLUME/K/N,P=POSITION/K/N,PRI=PRIORITY/K/N,L=LENGTH/K/N,
  1347.  *        S=SECONDS/K/N,BUF=BUFFER/K/N"
  1348.  *
  1349.  *
  1350.  *         BITS can be one of 8, 16 or 32. CHANNELS can be either 1 or 2.
  1351.  *        The FREQUENCY is in Herz, TYPE is one of SIGNED, AIFF or AIFC.
  1352.  *        VOLUME ranges from 0 (silence) to 100 (full volume), and POSITION
  1353.  *        ranges from -100 (far left) via 0 (center) to 100 (far right).
  1354.  *        The PRIORITY is only used when writing, and can be from -128 to
  1355.  *        127 (unstoppable). LENGTH is how many bytes you wish to read or
  1356.  *        write, and SECONDS is the same, but in seconds instead of bytes.
  1357.  *        The BUFFER size is specified in bytes. Note that two buffers are
  1358.  *        always used, which means that the memory usage will be 2×BUFFER.
  1359.  *
  1360.  *
  1361.  *         The default options for reading:
  1362.  *        BITS=8 CHANNELS=1 FREQUENCY=8000 TYPE=SIGNED LENGTH=very-very-much
  1363.  *        BUFFER=32768.
  1364.  *
  1365.  *         The default options for reading:
  1366.  *        BITS=8 CHANNELS=1 FREQUENCY=8000 TYPE=<none> VOLUME=100 POSITION=0
  1367.  *        PRIORITY=0 LENGTH=very-very-much BUFFER=32768.
  1368.  *
  1369.  *         If TYPE is not specified, the default behavour is to identify the
  1370.  *        data stream as IFF-AIFF or IFF-AIFC. If so, the default values of
  1371.  *        BITS, CHANNELS, FREQUENCY and LENGTH will be changed. You can still
  1372.  *        override them if you wish. If the stream could not be identified,
  1373.  *        the data format is assumed to be SIGNED.
  1374.  *
  1375.  *
  1376.  *         Both when reading and writing the sample rate will be converted
  1377.  *        on the fly to what the underlying hardware is configured to.
  1378.  *        Normally this is not a big problem when writing, but the quality
  1379.  *        when reading leaves quite a lot to wish for, since no low-pass
  1380.  *        filters are used.
  1381. d68 1
  1382. a68 1
  1383. long AllocAudio(void);
  1384. d101 1
  1385. a101 1
  1386. const static char ID[] = "$VER: AHI-Handler 1.6 (1.2.96)\r\n";
  1387. d158 3
  1388. d213 1
  1389. d253 5
  1390. a257 1
  1391.         if(packet->dp_Res2 = AllocAudio()) {
  1392. d800 1
  1393. a800 1
  1394. long AllocAudio(void) {
  1395. d807 1
  1396. a807 1
  1397.         AHIDevice=OpenDevice(AHINAME,0,(struct IORequest *)AHIio,NULL);
  1398. d833 1
  1399. a833 1
  1400.     if(!AHIDevice)
  1401. d865 1
  1402. a865 1
  1403.       "PRI=PRIORITY/K/N,L=LENGTH/K/N,S=SECONDS/K/N,BUF=BUFFER/K/N",
  1404. @
  1405.  
  1406.  
  1407. 1.5
  1408. log
  1409. @It's "finished"!
  1410. @
  1411. text
  1412. @d1 1
  1413. a1 1
  1414. /* $Id: main.c,v 1.4 1997/01/24 23:20:47 lcs Exp lcs $
  1415. d3 3
  1416. d145 1
  1417. a145 1
  1418. const static char ID[] = "$VER: AHI-Handler 1.5 (29.1.96)\r\n";
  1419. d423 1
  1420. a423 1
  1421.               packet->dp_Res1 = -1;
  1422. d805 1
  1423. a805 2
  1424. /*
  1425.       data->totallength = common->numSampleFrames *
  1426. a806 1
  1427. */
  1428. a812 1
  1429. /*
  1430. a814 1
  1431. */
  1432. a912 3
  1433.       else if(Stricmp("UNSIGNED", data->args.type) == 0) {
  1434.         data->args.format = UNSIGNED;
  1435.       }
  1436. a947 1
  1437. #define Sunsignedflag  4
  1438. d950 3
  1439. a952 2
  1440.   ULONG bits = 8, channels = 1, freq = 8000, volume = 100, position = 0;
  1441.   LONG priority = 0, length = MAXINT, buffersize = 32768;
  1442. d1006 6
  1443. a1011 1
  1444.   data->pos      = *data->args.position * 0x8000 / 100 + 0x8000;
  1445. d1013 1
  1446. a1025 3
  1447.     case UNSIGNED:
  1448.       data->type |= Sunsignedflag;
  1449.       break;
  1450. @
  1451.  
  1452.  
  1453. 1.4
  1454. log
  1455. @Writing seem to work too...
  1456. @
  1457. text
  1458. @d1 1
  1459. a1 1
  1460. /* $Id: main.c,v 1.3 1997/01/23 19:55:50 lcs Exp lcs $
  1461. d3 3
  1462. d23 48
  1463. d103 2
  1464. d106 3
  1465. d111 2
  1466. a112 1
  1467. long InitHData(struct HandlerData *, char *);
  1468. d142 2
  1469. d184 4
  1470. d207 1
  1471. d209 1
  1472. a236 3
  1473.         kprintf("Die!\n");
  1474.         if(AllocCnt == 0)
  1475.           Running = FALSE;
  1476. d240 2
  1477. d275 1
  1478. d277 12
  1479. d292 1
  1480. a295 1
  1481.         data = AllocVec(sizeof(struct HandlerData), MEMF_PUBLIC | MEMF_CLEAR);
  1482. d297 2
  1483. a298 9
  1484.         if(packet->dp_Res2 = InitHData(data, (char *) buf)) {
  1485.           FreeHData(data);
  1486.           data = NULL;
  1487.           FreeAudio();
  1488.         }
  1489.         else {
  1490.           fh->fh_Arg1 = (ULONG) data;
  1491.           fh->fh_Port = (struct MsgPort *) DOS_TRUE;
  1492.         }
  1493. d302 2
  1494. d324 1
  1495. d326 8
  1496. d383 1
  1497. a383 8
  1498.             AIFFHeader.FORMsize = sizeof(AIFFHeader) + data->totallength - 8;
  1499.             AIFFHeader.COMMchunk.numChannels = data->channels;
  1500.             AIFFHeader.COMMchunk.numSampleFrames = 
  1501.                 data->totallength / AHI_SampleFrameSize(data->type);
  1502.             AIFFHeader.COMMchunk.sampleSize = data->bits;
  1503.             ulong2extended(data->freq, &AIFFHeader.COMMchunk.sampleRate);
  1504.             AIFFHeader.SSNDsize =
  1505.                 sizeof(SampledSoundHeader) + data->totallength;
  1506. d396 1
  1507. a396 8
  1508.             AIFCHeader.FORMsize = sizeof(AIFCHeader) + data->totallength - 8;
  1509.             AIFCHeader.COMMchunk.numChannels = data->channels;
  1510.             AIFCHeader.COMMchunk.numSampleFrames = 
  1511.                 data->totallength / AHI_SampleFrameSize(data->type);
  1512.             AIFCHeader.COMMchunk.sampleSize = data->bits;
  1513.             ulong2extended(data->freq, &AIFCHeader.COMMchunk.sampleRate);
  1514.             AIFCHeader.SSNDsize =
  1515.                 sizeof(SampledSoundHeader) + data->totallength;
  1516. d448 2
  1517. d454 16
  1518. a469 1
  1519.         long   length, filled;
  1520. d471 6
  1521. d478 25
  1522. a502 1
  1523.         kprintf("ACTION_WRITE: 0x%08lx, %ld\n", packet->dp_Arg2, packet->dp_Arg3);
  1524. d504 2
  1525. a505 1
  1526.         length = filled = min(data->totallength, packet->dp_Arg3);
  1527. d507 1
  1528. a507 1
  1529.         if(data->buffer1 == NULL) {
  1530. d520 1
  1531. a520 1
  1532.           kprintf("length: %ld\n", data->length);
  1533. d523 2
  1534. d530 4
  1535. a533 21
  1536.             void *temp;
  1537.  
  1538.             temp          = data->buffer1;
  1539.             data->buffer1 = data->buffer2;
  1540.             data->buffer2 = temp;
  1541.  
  1542.  
  1543.             temp            = data->writereq1;
  1544.             data->writereq1 = data->writereq2;
  1545.             data->writereq2 = temp;
  1546.  
  1547.  
  1548.             if(data->writereq1) {
  1549.   kprintf("Väntar på 0x%08lx..\n",data->writereq1);
  1550.               WaitIO((struct IORequest *) data->writereq1);
  1551.  
  1552.               if(data->writereq1->ahir_Std.io_Error) {
  1553.                 packet->dp_Res1 = -1;
  1554.                 length = 0;
  1555.                 break;
  1556.               }
  1557. d535 1
  1558. a535 26
  1559.             else {
  1560.               data->writereq1 = AllocVec(sizeof (struct AHIRequest), MEMF_PUBLIC);
  1561.  
  1562.               if(data->writereq1 == NULL) {
  1563.                 packet->dp_Res1 = -1;
  1564.                 length = 0;
  1565.                 break;
  1566.               }
  1567.               CopyMem(AHIio, data->writereq1, sizeof (struct AHIRequest));
  1568.             }
  1569.  
  1570.             data->offset = 0;
  1571.  
  1572.   kprintf("Spelar 0x%08lx, länkad till 0x%08lx..\n", data->writereq1, data->writereq2);
  1573.             data->writereq1->ahir_Std.io_Message.mn_Node.ln_Pri = 0;
  1574.             data->writereq1->ahir_Std.io_Command = CMD_WRITE;
  1575.             data->writereq1->ahir_Std.io_Data    = data->buffer2;
  1576.             data->writereq1->ahir_Std.io_Length  = data->buffersize;
  1577.             data->writereq1->ahir_Std.io_Offset  = 0;
  1578.             data->writereq1->ahir_Type           = data->type;
  1579.             data->writereq1->ahir_Frequency      = data->freq;
  1580.             data->writereq1->ahir_Volume         = data->vol;
  1581.             data->writereq1->ahir_Position       = data->pos;
  1582.             data->writereq1->ahir_Link           = data->writereq2;
  1583.             SendIO((struct IORequest *) data->writereq1);
  1584.           } /* if */
  1585. a537 1
  1586. kprintf("Kopierar %ld bytes..\n", thislength);
  1587. d543 1
  1588. d550 2
  1589. d556 1
  1590. d558 4
  1591. d566 12
  1592. a577 7
  1593.         if(data->writereq1) {
  1594.           AbortIO((struct IORequest *) data->writereq1);
  1595.           WaitIO((struct IORequest *) data->writereq1);
  1596.         }
  1597.         if(data->writereq2) {
  1598.           AbortIO((struct IORequest *) data->writereq2);
  1599.           WaitIO((struct IORequest *) data->writereq2);
  1600. a582 2
  1601.         if(AllocCnt == 0)
  1602.           Running = FALSE;
  1603. d587 8
  1604. a595 4
  1605.       {
  1606.         if(AllocCnt == 0)
  1607.           Running = FALSE;
  1608.         kprintf("Unknow packet!\n");
  1609. a597 1
  1610.       }
  1611. d601 3
  1612. d608 3
  1613. d615 1
  1614. d617 1
  1615. d623 115
  1616. d755 78
  1617. d859 4
  1618. d881 4
  1619. d886 1
  1620. a886 1
  1621.  *  Initialize the HandlerData data structure, parse the arguments
  1622. d889 2
  1623. a890 1
  1624. long InitHData(struct HandlerData *data, char *initstring)
  1625. d892 7
  1626. a898 1
  1627. // Returns 0 on success, else an error code
  1628. d900 4
  1629. a903 20
  1630. {
  1631.   struct RDArgs *rdargs, *rdargs2;
  1632.   ULONG bits = 8, channels = 1, rate = 8000, volume = 100, position = 0;
  1633.   LONG length = MAXINT, buffersize = 32768;
  1634.   STRPTR type = "SIGNED";
  1635.   BOOL rc = 0;
  1636.  
  1637.   struct {
  1638.     ULONG     *bits;
  1639.     ULONG     *channels;
  1640.     ULONG     *rate;
  1641.     STRPTR     type;
  1642.     Fixed     *volume;
  1643.     sposition *position;
  1644.     ULONG     *length;
  1645.     ULONG     *seconds;
  1646.     ULONG     *buffersize;
  1647.   } args = {
  1648.       &bits, &channels, &rate, type, &volume, &position, &length, NULL, &buffersize
  1649.     };
  1650. d905 1
  1651. a905 2
  1652.   if(data == NULL)
  1653.     return ERROR_NO_FREE_STORE;
  1654. d908 18
  1655. a925 20
  1656.   rdargs = (struct RDArgs *) AllocDosObjectTags(DOS_RDARGS, TAG_DONE);
  1657.   if(rdargs)
  1658.   {
  1659.     rdargs->RDA_Source.CS_Buffer = initstring;
  1660.     rdargs->RDA_Source.CS_Length = strlen(initstring);
  1661.     rdargs->RDA_Source.CS_CurChr = 0;
  1662.     rdargs->RDA_Flags |= RDAF_NOPROMPT;
  1663.  
  1664.     rdargs2 = ReadArgs(
  1665.       "B=BITS/K/N,C=CHANNELS/K/N,R=RATE/K/N,T=TYPE/K,V=VOLUME/K/N,P=POSITION/K/N,"
  1666.       "L=LENGTH/K/N,S=SECONDS/K/N,BUF=BUFFER/K/N",
  1667.       (LONG *) &args, rdargs);
  1668.  
  1669.     if(rdargs2 != NULL) {
  1670.       kprintf("%ld bits, %ld channels, %ld Hz, %s, %ld%% volume, position %ld%%, "
  1671.               "%ld bytes total, %ld seconds, %ld bytes buffer\n",
  1672.           *args.bits, *args.channels, *args.rate, args.type, *args.volume, *args.position,
  1673.           *args.length, (args.seconds ? *args.seconds : 0), *args.buffersize);
  1674.  
  1675.       FreeArgs(rdargs2);    
  1676. a929 1
  1677.     FreeDosObject(DOS_RDARGS, rdargs);
  1678. d932 4
  1679. a935 1
  1680.     rc = ERROR_OBJECT_WRONG_TYPE;
  1681. d938 8
  1682. a945 1
  1683.   if(rc == 0) {
  1684. d954 71
  1685. a1024 25
  1686.     // 8, 16 or 32 bit
  1687.   
  1688.     if(*args.bits <= 8)
  1689.       data->type = S8bitmode;
  1690.     else if(*args.bits <= 16)
  1691.       data->type = S16bitmode;
  1692.     else if(*args.bits <= 32)
  1693.       data->type = S32bitmode;
  1694.     else
  1695.       rc = ERROR_OBJECT_WRONG_TYPE;
  1696.   
  1697.     // Mono or stereo
  1698.   
  1699.     if(*args.channels == 2)
  1700.       data->type |= Sstereoflag;
  1701.     else if(*args.channels != 1)
  1702.       rc = ERROR_OBJECT_WRONG_TYPE;
  1703.   
  1704.     // Signed, unsigned, aiff, aifc...
  1705.   
  1706.     if(Stricmp("SIGNED", args.type) == 0) {
  1707.       data->format = RAW;
  1708.       kprintf("Signed\n");
  1709.     }
  1710.     else if(Stricmp("UNSIGNED", args.type) == 0) {
  1711. d1026 5
  1712. a1030 39
  1713.       data->format = RAW;
  1714.       kprintf("Unsigned\n");
  1715.     }
  1716.     else if(Stricmp("AIFF", args.type) == 0) {
  1717.       data->format = AIFF;
  1718.       kprintf("AIFF\n");
  1719.     }
  1720.     else if(Stricmp("AIFC", args.type) == 0) {
  1721.       data->format = AIFC;
  1722.       kprintf("AIFC\n");
  1723.     }
  1724.     else {
  1725.       rc = ERROR_OBJECT_WRONG_TYPE;
  1726.     }
  1727.   
  1728.     data->bits     = *args.bits;
  1729.     data->channels = *args.channels;
  1730.     data->freq     = *args.rate;
  1731.     data->vol      = *args.volume * 0x10000 / 100;
  1732.     data->pos      = *args.position * 0x8000 / 100 + 0x8000;
  1733.     if(args.seconds)
  1734.       data->totallength = *args.seconds * data->freq 
  1735.                           * AHI_SampleFrameSize(data->type);
  1736.     else
  1737.       data->totallength = (*args.length / AHI_SampleFrameSize(data->type))
  1738.                           * AHI_SampleFrameSize(data->type);
  1739.   
  1740.     switch(data->format) {
  1741.       case AIFF:
  1742.       case AIFC:
  1743.         data->totallength = (data->totallength + 1) & ~1;    // Make even
  1744.         break;
  1745.       default:
  1746.         break;
  1747.     }
  1748.   
  1749.     // User doesn't know about double buffering!
  1750.   
  1751.     data->buffersize = *args.buffersize >> 1;
  1752. d1033 3
  1753. d1040 13
  1754. d1057 14
  1755. a1070 8
  1756. void FreeHData(struct HandlerData *data)
  1757. {
  1758.   FreeVec(data->buffer1);
  1759.   FreeVec(data->buffer2);
  1760.   FreeVec(data->readreq);
  1761.   FreeVec(data->writereq1);
  1762.   FreeVec(data->writereq2);
  1763.   FreeVec(data);
  1764. d1074 4
  1765. d1084 1
  1766. a1084 3
  1767. void
  1768. returnpacket (struct DosPacket *packet)
  1769. {
  1770. d1095 5
  1771. a1131 3
  1772. /*
  1773.   dn->dn_Task = PktPort;
  1774. */
  1775. d1139 5
  1776. a1147 1
  1777.   /* dn->dn_SegList = NULL; */
  1778. @
  1779.  
  1780.  
  1781. 1.3
  1782. log
  1783. @Added AIFF and AIFC saving.
  1784. @
  1785. text
  1786. @d1 1
  1787. a1 1
  1788. /* $Id: main.c,v 1.2 1997/01/21 23:56:21 lcs Exp lcs $
  1789. d3 3
  1790. d15 6
  1791. a20 3
  1792. ** This code is written using DICE, just for testing, and is based on the
  1793. ** DosHan example source code.
  1794. */
  1795. d45 1
  1796. a45 1
  1797. #include "aifc.h"
  1798. d48 3
  1799. a50 6
  1800. #define min(a,b) ((a)<=(b)?(a):(b))
  1801. #define DOS_TRUE    -1
  1802. #define DOS_FALSE   0
  1803. #define BTOC(bptr)  ((void *)((long)(bptr) << 2))
  1804. #define CTOB(cptr)  ((BPTR)(((long)cptr) >> 2))
  1805.  
  1806. d61 16
  1807. a79 52
  1808. #define RAW          0
  1809. #define AIFF         1
  1810. #define AIFC         2
  1811.  
  1812. struct HandlerData {
  1813.   UBYTE             *buffer1;        // Address of read buffer
  1814.   UBYTE             *buffer2;
  1815.   LONG               length;         // Offset to first invalid sample frame
  1816.   LONG               offset;         // Current pointer
  1817.   struct AHIRequest *req;
  1818.   UWORD              bits;
  1819.   UWORD              channels;
  1820.   ULONG              type;
  1821.   ULONG              freq;
  1822.   Fixed              vol;
  1823.   sposition          pos;
  1824.   LONG               totallength;     // Total number of bytes to play/record
  1825.   LONG               buffersize;      // Play/record buffer size
  1826.   UBYTE              format;
  1827. };
  1828.  
  1829. struct AIFCHeader {
  1830.   ULONG                 FORMid;
  1831.   ULONG                 FORMsize;
  1832.   ULONG                 AIFCid;
  1833.  
  1834.   ULONG                 FVERid;
  1835.   ULONG                 FVERsize;
  1836.   FormatVersionHeader   FVERchunk;
  1837.  
  1838.   ULONG                 COMMid;
  1839.   ULONG                 COMMsize;
  1840.   ExtCommonChunk        COMMchunk;
  1841.  
  1842.   ULONG                 SSNDid;
  1843.   ULONG                 SSNDsize;
  1844.   SampledSoundHeader    SSNDchunk;
  1845. };
  1846.  
  1847. struct AIFFHeader {
  1848.   ULONG                 FORMid;
  1849.   ULONG                 FORMsize;
  1850.   ULONG                 AIFFid;
  1851.  
  1852.   ULONG                 COMMid;
  1853.   ULONG                 COMMsize;
  1854.   CommonChunk           COMMchunk;
  1855.  
  1856.   ULONG                 SSNDid;
  1857.   ULONG                 SSNDsize;
  1858.   SampledSoundHeader    SSNDchunk;
  1859. };
  1860. d81 3
  1861. d124 1
  1862. d266 1
  1863. d268 4
  1864. a271 2
  1865.           if((data->buffer1 == NULL) || (data->buffer2 == NULL)) {
  1866.             packet->dp_Res1 = -1;
  1867. d275 2
  1868. d280 9
  1869. a288 9
  1870.           data->req->ahir_Std.io_Command                 = CMD_READ;
  1871.           data->req->ahir_Std.io_Data                    = data->buffer2;
  1872.           data->req->ahir_Std.io_Length                  = data->buffersize;
  1873.           data->req->ahir_Std.io_Offset                  = 0;
  1874.           data->req->ahir_Type                           = data->type;
  1875.           data->req->ahir_Frequency                      = data->freq;
  1876.           data->req->ahir_Volume                         = data->vol;
  1877.           data->req->ahir_Position                       = data->pos;
  1878.           SendIO((struct IORequest *) data->req);
  1879. d348 2
  1880. a349 2
  1881.             WaitIO((struct IORequest *) data->req);
  1882.             data->length = data->req->ahir_Std.io_Actual;
  1883. d352 1
  1884. a352 1
  1885.             if(data->req->ahir_Std.io_Error) {
  1886. d358 8
  1887. a365 8
  1888.             data->req->ahir_Std.io_Command                 = CMD_READ;
  1889.             data->req->ahir_Std.io_Data                    = data->buffer2;
  1890.             data->req->ahir_Std.io_Length                  = data->buffersize;
  1891.             data->req->ahir_Type                           = data->type;
  1892.             data->req->ahir_Frequency                      = data->freq;
  1893.             data->req->ahir_Volume                         = data->vol;
  1894.             data->req->ahir_Position                       = data->pos;
  1895.             SendIO((struct IORequest *) data->req);
  1896. d384 7
  1897. a390 1
  1898.         long bytes = packet->dp_Arg3;
  1899. d392 4
  1900. a395 1
  1901.         packet->dp_Res1 = -1;
  1902. d397 1
  1903. a397 12
  1904.         kprintf("ACTION_WRITE: 0x%08lx, %ld\n", packet->dp_Arg2, bytes);
  1905. #if 0
  1906.         if (xn = AllocMem (sizeof (XNode), MEMF_PUBLIC | MEMF_CLEAR)) {
  1907.           if (xn->xn_Buf = AllocMem (bytes, MEMF_PUBLIC)) {
  1908.             movmem ((char *) packet->dp_Arg2, xn->xn_Buf, bytes);
  1909.             xn->xn_Length = bytes;
  1910.             packet->dp_Res1 = bytes;
  1911.             AddTail (&xh->xh_List, &xn->xn_Node);
  1912.             xh->xh_Flags &= ~XHF_EOF;
  1913.           }
  1914.           else {
  1915.             FreeMem (xn, sizeof (XNode));
  1916. d399 1
  1917. d401 5
  1918. d407 65
  1919. a471 4
  1920.         else {
  1921.           packet->dp_Res2 = ERROR_NO_FREE_STORE;
  1922.         }
  1923. #endif
  1924. d480 12
  1925. a491 2
  1926.         AbortIO((struct IORequest *) data->req);
  1927.         WaitIO((struct IORequest *) data->req);
  1928. d504 3
  1929. d522 1
  1930. a522 1
  1931.   UnInitialize ();
  1932. d634 5
  1933. a638 4
  1934.     kprintf("%ld bits, %ld channels, %ld Hz, %s, %ld%% volume, position %ld%%, "
  1935.             "%ld bytes total, %ld seconds, %ld bytes buffer\n",
  1936.         *args.bits, *args.channels, *args.rate, args.type, *args.volume, *args.position,
  1937.         *args.length, (args.seconds ? *args.seconds : 0), *args.buffersize);
  1938. d640 1
  1939. a640 2
  1940.     if(data->req = AllocVec(sizeof (struct AHIRequest), MEMF_PUBLIC) ) {
  1941.       CopyMem(AHIio, data->req, sizeof (struct AHIRequest));
  1942. d643 1
  1943. a643 1
  1944.       rc = ERROR_NO_FREE_STORE;
  1945. a644 1
  1946.     FreeArgs(rdargs2);    
  1947. d650 3
  1948. d660 65
  1949. a724 36
  1950.   // 8, 16 or 32 bit
  1951.  
  1952.   if(*args.bits <= 8)
  1953.     data->type = S8bitmode;
  1954.   else if(*args.bits <= 16)
  1955.     data->type = S16bitmode;
  1956.   else if(*args.bits <= 32)
  1957.     data->type = S32bitmode;
  1958.   else
  1959.     rc = ERROR_OBJECT_WRONG_TYPE;
  1960.  
  1961.   // Mono or stereo
  1962.  
  1963.   if(*args.channels == 2)
  1964.     data->type |= Sstereoflag;
  1965.   else if(*args.channels != 1)
  1966.     rc = ERROR_OBJECT_WRONG_TYPE;
  1967.  
  1968.   // Signed, unsigned, aiff, aifc...
  1969.  
  1970.   if(Stricmp("SIGNED", args.type) == 0) {
  1971.     data->format = RAW;
  1972.     kprintf("Signed\n");
  1973.   }
  1974.   else if(Stricmp("UNSIGNED", args.type) == 0) {
  1975.     data->type |= Sunsignedflag;
  1976.     data->format = RAW;
  1977.     kprintf("Unsigned\n");
  1978.   }
  1979.   else if(Stricmp("AIFF", args.type) == 0) {
  1980.     data->format = AIFF;
  1981.     kprintf("AIFF\n");
  1982.   }
  1983.   else if(Stricmp("AIFC", args.type) == 0) {
  1984.     data->format = AIFC;
  1985.     kprintf("AIFC\n");
  1986. a725 26
  1987.   else {
  1988.     rc = ERROR_OBJECT_WRONG_TYPE;
  1989.   }
  1990.  
  1991.   data->bits     = *args.bits;
  1992.   data->channels = *args.channels;
  1993.   data->freq     = *args.rate;
  1994.   data->vol      = *args.volume * 0x10000 / 100;
  1995.   data->pos      = *args.position * 0x8000 / 100 + 0x8000;
  1996.   if(args.seconds)
  1997.     data->totallength = *args.seconds * data->freq 
  1998.                         * AHI_SampleFrameSize(data->type);
  1999.   else
  2000.     data->totallength = (*args.length / AHI_SampleFrameSize(data->type))
  2001.                         * AHI_SampleFrameSize(data->type);
  2002.  
  2003.   switch(data->format) {
  2004.     case AIFF:
  2005.     case AIFC:
  2006.       data->totallength = (data->totallength + 1) & ~1;    // Make even
  2007.       break;
  2008.     default:
  2009.       break;
  2010.   }
  2011.  
  2012.   // User doesn't know about double buffering!
  2013. a726 1
  2014.   data->buffersize = *args.buffersize >> 1;
  2015. d739 3
  2016. a741 1
  2017.   FreeVec(data->req);
  2018. @
  2019.  
  2020.  
  2021. 1.2
  2022. log
  2023. @Reading seem to work okay now.
  2024. @
  2025. text
  2026. @d1 1
  2027. a1 1
  2028. /* $Id: main.c,v 1.1 1997/01/17 23:34:28 lcs Exp lcs $
  2029. d3 3
  2030. a15 1
  2031. #define min(a,b) ((a)<=(b)?(a):(b))
  2032. a33 1
  2033.  
  2034. d39 4
  2035. d45 12
  2036. d61 3
  2037. a63 3
  2038. #define BTOC(bptr)  ((void *)((long)(bptr) << 2))
  2039. #define CTOB(cptr)  ((BPTR)(((long)cptr) >> 2))
  2040.  
  2041. d71 2
  2042. d79 1
  2043. d82 31
  2044. a112 4
  2045. long AllocAudio(void);
  2046. void FreeAudio(void);
  2047. long InitHData(struct HandlerData *, char *);
  2048. void FreeHData(struct HandlerData *);
  2049. a113 3
  2050. void returnpacket (struct DosPacket *);
  2051. void Initialize (void);
  2052. void UnInitialize (void);
  2053. d124 29
  2054. d218 1
  2055. d221 4
  2056. a224 1
  2057.         base++;
  2058. a225 1
  2059.         { // Convert /'s to blanks
  2060. d227 1
  2061. a245 1
  2062.         
  2063. d273 1
  2064. a273 1
  2065.          *  the buffer, we wait until the other is filed, and switch
  2066. d292 1
  2067. d303 1
  2068. d315 1
  2069. d317 42
  2070. d444 4
  2071. d474 17
  2072. d508 3
  2073. d605 1
  2074. d616 1
  2075. d622 7
  2076. a628 2
  2077.   // Signed or unsigned
  2078.   if(Stricmp("UNSIGNED", args.type) == 0)
  2079. d630 12
  2080. a641 1
  2081.   else if(Stricmp("SIGNED", args.type) != 0)
  2082. a642 10
  2083.  
  2084.   data->freq = *args.rate;
  2085.   data->vol  = *args.volume * 0x10000 / 100;
  2086.   data->pos  = *args.position * 0x8000 / 100 + 0x8000;
  2087.  
  2088.   if(data->vol > 0x10000) {
  2089.     data->vol = 0x10000;
  2090.   }
  2091.   if(data->pos > 0x10000) {
  2092.     data->pos = 0x10000;
  2093. d645 5
  2094. d651 2
  2095. a652 1
  2096.     data->totallength = *args.seconds * data->freq;
  2097. d654 11
  2098. a664 1
  2099.     data->totallength = *args.length;
  2100. d667 1
  2101. d737 1
  2102. d739 2
  2103. @
  2104.  
  2105.  
  2106. 1.1
  2107. log
  2108. @Initial revision
  2109. @
  2110. text
  2111. @d1 5
  2112. a5 2
  2113. /* $Id$
  2114.  * $Log$
  2115. d8 7
  2116. d22 4
  2117. d29 3
  2118. a31 1
  2119. #include <lists.h>
  2120. d41 3
  2121. a46 25
  2122. typedef struct DosPacket DosPacket;
  2123. typedef struct FileHandle FileHandle;
  2124. typedef struct DeviceNode DeviceNode;
  2125. typedef struct Process Process;
  2126. typedef struct Node Node;
  2127. typedef struct List List;
  2128. typedef struct MsgPort MsgPort;
  2129. typedef struct Message Message;
  2130.  
  2131. typedef struct XHandle {
  2132.   Node xh_Node;
  2133.   long xh_XHLen;
  2134.   long xh_Refs;
  2135.   long xh_Flags;
  2136.   List xh_List;
  2137. } XHandle;
  2138.  
  2139. #define XHF_EOF     0x0001
  2140.  
  2141. typedef struct XNode {
  2142.   Node xn_Node;
  2143.   char *xn_Buf;
  2144.   long xn_Offset;
  2145.   long xn_Length;
  2146. } XNode;
  2147. d48 20
  2148. a67 1
  2149. void returnpacket (DosPacket *);
  2150. d71 9
  2151. a79 4
  2152.  
  2153. List HanList;
  2154. DeviceNode *DevNode;
  2155. MsgPort *PktPort;
  2156. d89 5
  2157. a93 5
  2158.   DosPacket *packet;
  2159.   {
  2160.     Process *proc = (struct Process *) FindTask (NULL);
  2161.     PktPort = &proc->pr_MsgPort;
  2162.   }
  2163. d97 5
  2164. d106 21
  2165. a126 2
  2166.   for (;;)
  2167.     {
  2168. d128 30
  2169. a157 1
  2170.         Message *msg;
  2171. d159 24
  2172. a182 3
  2173.         while ((msg = GetMsg (PktPort)) == NULL)
  2174.           Wait (1 << PktPort->mp_SigBit);
  2175.         packet = (DosPacket *) msg->mn_Node.ln_Name;
  2176. d185 27
  2177. a211 14
  2178.       /*
  2179.        *  default return value
  2180.        */
  2181.  
  2182.       packet->dp_Res1 = DOS_TRUE;
  2183.       packet->dp_Res2 = 0;
  2184.  
  2185.       /*
  2186.        *  switch on packet
  2187.        */
  2188.  
  2189.       switch (packet->dp_Type)
  2190.         {
  2191.         case ACTION_DIE:        /*  ??? */
  2192. d213 46
  2193. a258 28
  2194.         case ACTION_FINDUPDATE: /*  FileHandle,Lock,Name        Bool        */
  2195.         case ACTION_FINDINPUT:  /*  FileHandle,Lock,Name        Bool        */
  2196.         case ACTION_FINDOUTPUT: /*  FileHandle,Lock,Name        Bool        */
  2197.           {
  2198.             FileHandle *fh = BTOC (packet->dp_Arg1);
  2199.             XHandle *xh;
  2200.  
  2201.             {
  2202.               unsigned char *base = BTOC (packet->dp_Arg3);
  2203.               int len = *base;
  2204.               char buf[128];
  2205.  
  2206.               if (len >= sizeof (buf))
  2207.                 len = sizeof (buf) - 1;
  2208.  
  2209.               strncpy (buf, base + 1, len);
  2210.               buf[len] = 0;
  2211.  
  2212.               if ((xh = (XHandle *) FindName (&HanList, buf)) == NULL)
  2213.                 {
  2214.                   xh = AllocMem (sizeof (XHandle) + len + 1, MEMF_PUBLIC | MEMF_CLEAR);
  2215.                   xh->xh_XHLen = sizeof (XHandle) + len + 1;
  2216.                   xh->xh_Node.ln_Name = (char *) (xh + 1);
  2217.                   movmem (buf, xh->xh_Node.ln_Name, len + 1);
  2218.                   NewList (&xh->xh_List);
  2219.                   AddTail (&HanList, &xh->xh_Node);
  2220.                 }
  2221.               ++xh->xh_Refs;
  2222. a259 54
  2223.             fh->fh_Arg1 = (ULONG) xh;
  2224.             fh->fh_Port = (MsgPort *) DOS_TRUE;
  2225.           }
  2226.           break;
  2227.         case ACTION_READ:        /*  FHArg1,CPTRBuffer,Length    ActLength   */
  2228.           /*
  2229.            *        reading is straightforward except for handling EOF ... we
  2230.            *  must guarentee a return value of 0 (no bytes left) before
  2231.            *  beginning to return EOFs (-1's).  If we return a negative
  2232.            *  number right off programs like COPY will assume a failure
  2233.            *  (if TEST: is the source) and delete the destination file
  2234.            */
  2235.  
  2236.           {
  2237.             XHandle *xh = (XHandle *) packet->dp_Arg1;
  2238.             long bytes;
  2239.  
  2240.             packet->dp_Res1 = 0;
  2241.             while ((bytes = packet->dp_Arg3 - packet->dp_Res1) > 0)
  2242.               {
  2243.                 XNode *xn = (XNode *) RemHead (&xh->xh_List);
  2244.  
  2245.                 if (xn == NULL)
  2246.                   break;
  2247.  
  2248.                 if (bytes > xn->xn_Length - xn->xn_Offset)
  2249.                   bytes = xn->xn_Length - xn->xn_Offset;
  2250.                 movmem (xn->xn_Buf + xn->xn_Offset, (char *) packet->dp_Arg2 + packet->dp_Res1, bytes);
  2251.  
  2252.                 xn->xn_Offset += bytes;
  2253.                 packet->dp_Res1 += bytes;
  2254.                 if (xn->xn_Offset == xn->xn_Length)
  2255.                   {
  2256.                     FreeMem (xn->xn_Buf, xn->xn_Length);
  2257.                     FreeMem (xn, sizeof (XNode));
  2258.                   }
  2259.                 else
  2260.                   {
  2261.                     AddHead (&xh->xh_List, &xn->xn_Node);
  2262.                   }
  2263.               }
  2264.             if (packet->dp_Res1 == 0 && GetHead (&xh->xh_List) == NULL)
  2265.               {
  2266.                 if (xh->xh_Flags & XHF_EOF)
  2267.                   packet->dp_Res1 = -1;                /*  EOF */
  2268.                 xh->xh_Flags |= XHF_EOF;
  2269.               }
  2270.           }
  2271.           break;
  2272.         case ACTION_WRITE:        /*  FHArg1,CPTRBuffer,Length    ActLength   */
  2273.           {
  2274.             XHandle *xh = (XHandle *) packet->dp_Arg1;
  2275.             XNode *xn;
  2276.             long bytes = packet->dp_Arg3;
  2277. d261 39
  2278. a299 21
  2279.             packet->dp_Res1 = -1;
  2280.             if (xn = AllocMem (sizeof (XNode), MEMF_PUBLIC | MEMF_CLEAR))
  2281.               {
  2282.                 if (xn->xn_Buf = AllocMem (bytes, MEMF_PUBLIC))
  2283.                   {
  2284.                     movmem ((char *) packet->dp_Arg2, xn->xn_Buf, bytes);
  2285.                     xn->xn_Length = bytes;
  2286.                     packet->dp_Res1 = bytes;
  2287.                     AddTail (&xh->xh_List, &xn->xn_Node);
  2288.                     xh->xh_Flags &= ~XHF_EOF;
  2289.                   }
  2290.                 else
  2291.                   {
  2292.                     FreeMem (xn, sizeof (XNode));
  2293.                     packet->dp_Res2 = ERROR_NO_FREE_STORE;
  2294.                   }
  2295.               }
  2296.             else
  2297.               {
  2298.                 packet->dp_Res2 = ERROR_NO_FREE_STORE;
  2299.               }
  2300. d301 3
  2301. a303 11
  2302.           break;
  2303.         case ACTION_END:        /*  FHArg1                      Bool:TRUE   */
  2304.           {
  2305.             XHandle *xh = (XHandle *) packet->dp_Arg1;
  2306.  
  2307.             if (--xh->xh_Refs == 0 && GetHead (&xh->xh_List) == NULL)
  2308.               {
  2309.                 Remove (&xh->xh_Node);
  2310.                 FreeMem (xh, xh->xh_XHLen);
  2311.               }
  2312.             break;
  2313. a304 4
  2314.           break;
  2315.         default:
  2316.           packet->dp_Res2 = ERROR_ACTION_NOT_KNOWN;
  2317.           break;
  2318. d306 2
  2319. a307 5
  2320.       if (packet)
  2321.         {
  2322.           if (packet->dp_Res2)
  2323.             packet->dp_Res1 = DOS_FALSE;
  2324.           returnpacket (packet);
  2325. d309 29
  2326. d340 1
  2327. a340 3
  2328.   /*
  2329.    *        no reached
  2330.    */
  2331. d342 1
  2332. d349 168
  2333. d523 1
  2334. a523 2
  2335. returnpacket (packet)
  2336.      DosPacket *packet;
  2337. d525 2
  2338. a526 2
  2339.   Message *mess;
  2340.   MsgPort *replyPort;
  2341. d551 4
  2342. a554 6
  2343. void
  2344. Initialize ()
  2345. {
  2346.   DeviceNode *dn;
  2347.   Process *proc = (Process *) FindTask (NULL);
  2348.   DosPacket *packet;
  2349. d559 2
  2350. d562 3
  2351. a564 7
  2352.   {
  2353.     Message *msg;
  2354.  
  2355.     WaitPort (PktPort);
  2356.     msg = GetMsg (PktPort);
  2357.     packet = (DosPacket *) msg->mn_Node.ln_Name;
  2358.   }
  2359. d566 2
  2360. a567 2
  2361.   {
  2362.     DevNode = dn = BTOC (packet->dp_Arg3);
  2363. a568 2
  2364.     dn->dn_Task = PktPort;
  2365.   }
  2366. d574 2
  2367. a575 5
  2368. void
  2369. UnInitialize (void)
  2370. {
  2371.   {
  2372.     DeviceNode *dn = DevNode;
  2373. d577 2
  2374. a578 3
  2375.     dn->dn_Task = NULL;
  2376.     /* dn->dn_SegList = NULL; */
  2377.   }
  2378. @
  2379.